package com.framework.test.utils;

import com.framework.test.context.GlobalContext;
import com.framework.test.exceptions.AutomationException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.yaml.snakeyaml.Yaml;

import java.io.*;
import java.text.MessageFormat;
import java.util.*;

/**
 * 配置管理器 - 支持Properties和YAML格式，支持环境配置
 * 
 * 配置文件加载优先级：
 * 1. application.properties
 * 2. application.yml
 * 3. application-{profile}.properties
 * 4. application-{profile}.yml
 */
public final class ConfigurationManager {
    private static final Logger logger = LogManager.getLogger(ConfigurationManager.class);
    
    private static final ConfigurationManager INSTANCE = new ConfigurationManager();
    private static Properties mergedProperties;
    private static String activeProfile;
    
    static {
        activeProfile = getActiveProfile();
    }
    
    private ConfigurationManager() {}
    
    public static ConfigurationManager getInstance() {
        if (mergedProperties == null) {
            INSTANCE.loadConfiguration();
        }
        return INSTANCE;
    }
    
    /**
     * 获取激活的profile
     */
    public static String getActiveProfile() {
        if (activeProfile != null) {
            return activeProfile;
        }
        
        String profile = System.getProperty("framework.profiles.active", 
                        System.getenv("FRAMEWORK_PROFILES_ACTIVE"));
        return (profile == null || profile.trim().isEmpty()) ? "default" : profile;
    }
    
    /**
     * 加载配置文件
     */
    private void loadConfiguration() {
        mergedProperties = new Properties();
        if (activeProfile == null) {
            activeProfile = getActiveProfile();
        }
        
        logger.info("Loading Configuration with profile: {}", activeProfile);
        
        try {
            // 按优先级加载配置文件
            loadConfigFile("application.properties");
            loadConfigFile("application.yml");
            
            if (!"default".equals(activeProfile)) {
                loadConfigFile("application-" + activeProfile + ".properties");
                loadConfigFile("application-" + activeProfile + ".yml");
            }
            
            logger.info("Configuration loaded successfully. Total properties: {}", mergedProperties.size());
        } catch (Exception e) {
            logger.error("Error loading configuration: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 加载配置文件（统一处理Properties和YAML）
     */
    private void loadConfigFile(String fileName) {
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream(fileName);
        if (inputStream == null) {
            logger.debug("Configuration file not found: {}", fileName);
            return;
        }
        
        try (InputStream is = inputStream) {
            if (fileName.endsWith(".yml") || fileName.endsWith(".yaml")) {
                loadYamlProperties(is, fileName);
            } else {
                loadProperties(is, fileName);
            }
        } catch (Exception e) {
            logger.warn("Failed to load configuration file: {}", fileName, e);
        }
    }
    
    /**
     * 加载Properties文件
     */
    private void loadProperties(InputStream inputStream, String fileName) throws IOException {
        Properties props = new Properties();
        props.load(inputStream);
        mergedProperties.putAll(props);
        logger.debug("Loaded properties from: {} ({} properties)", fileName, props.size());
    }
    
    /**
     * 加载YAML文件
     */
    private void loadYamlProperties(InputStream inputStream, String fileName) {
        try {
            Yaml yaml = new Yaml();
            Map<String, Object> yamlData = yaml.load(inputStream);
            
            if (yamlData != null) {
                Properties yamlProps = flattenYamlToProperties(yamlData, "");
                mergedProperties.putAll(yamlProps);
                logger.debug("Loaded YAML from: {} ({} properties)", fileName, yamlProps.size());
            }
        } catch (Exception e) {
            logger.warn("Failed to parse YAML file: {}", fileName, e);
        }
    }
    
    /**
     * 将嵌套的YAML结构转换为扁平的Properties格式
     */
    @SuppressWarnings("unchecked")
    private Properties flattenYamlToProperties(Map<String, Object> yamlData, String prefix) {
        Properties properties = new Properties();
        
        for (Map.Entry<String, Object> entry : yamlData.entrySet()) {
            String key = prefix.isEmpty() ? entry.getKey() : prefix + "." + entry.getKey();
            Object value = entry.getValue();
            
            if (value instanceof Map) {
                properties.putAll(flattenYamlToProperties((Map<String, Object>) value, key));
            } else if (value instanceof List) {
                List<?> list = (List<?>) value;
                for (int i = 0; i < list.size(); i++) {
                    Object listItem = list.get(i);
                    String listKey = key + "[" + i + "]";
                    if (listItem instanceof Map) {
                        properties.putAll(flattenYamlToProperties((Map<String, Object>) listItem, listKey));
                    } else {
                        properties.setProperty(listKey, String.valueOf(listItem));
                    }
                }
            } else if (value != null) {
                properties.setProperty(key, String.valueOf(value));
            }
        }
        
        return properties;
    }
    
    /**
     * 获取属性值
     */
    public static String getProperty(String propertyName) throws AutomationException {
        getInstance();
        Object value = mergedProperties.get(propertyName);
        if (value != null) {
            String stringValue = value.toString();
            return GlobalContext.getInstance().replacePlaceholders(stringValue);
        } else {
            String errorLog = MessageFormat.format(
                "Property ''{0}'' not found in configuration files. Active profile: {1}", 
                propertyName, activeProfile);
            throw new AutomationException(errorLog);
        }
    }
    
    /**
     * 获取属性值，如果不存在则返回默认值
     */
    public static String getProperty(String propertyName, String defaultValue) {
        try {
            return getProperty(propertyName);
        } catch (Exception e) {
            return defaultValue;
        }
    }
    
    /**
     * 获取布尔属性值
     */
    public static boolean getBooleanProperty(String propertyName, boolean defaultValue) {
        try {
            String value = getProperty(propertyName);
            return Boolean.parseBoolean(value);
        } catch (Exception e) {
            return defaultValue;
        }
    }
    
    /**
     * 获取整数属性值
     */
    public static int getIntegerProperty(String propertyName, int defaultValue) {
        try {
            String value = getProperty(propertyName);
            return Integer.parseInt(value);
        } catch (Exception e) {
            return defaultValue;
        }
    }
    
    /**
     * 获取所有属性
     */
    public static Properties getAllProperties() throws AutomationException {
        getInstance();
        if (mergedProperties == null || mergedProperties.isEmpty()) {
            throw new AutomationException("Failed to load configuration");
        }
        
        Properties result = new Properties();
        GlobalContext context = GlobalContext.getInstance();
        for (String key : mergedProperties.stringPropertyNames()) {
            String value = mergedProperties.getProperty(key);
            String processedValue = context.replacePlaceholders(value);
            result.setProperty(key, processedValue);
        }
        return result;
    }
    
    /**
     * 设置激活的profile（主要用于测试）
     */
    public static void setActiveProfile(String profile) {
        activeProfile = profile;
        mergedProperties = null; // 重置配置，下次访问时重新加载
    }
    
    /**
     * 重新加载配置
     */
    public static void reload() {
        activeProfile = null; // 重置profile，重新读取系统属性
        mergedProperties = null;
        getInstance();
    }
    
    /**
     * 获取指定前缀的所有属性
     */
    public static Properties getPropertiesWithPrefix(String prefix) {
        getInstance();
        Properties result = new Properties();
        String prefixWithDot = prefix.endsWith(".") ? prefix : prefix + ".";
        GlobalContext context = GlobalContext.getInstance();
        
        for (String key : mergedProperties.stringPropertyNames()) {
            if (key.startsWith(prefixWithDot)) {
                String newKey = key.substring(prefixWithDot.length());
                String value = mergedProperties.getProperty(key);
                String processedValue = context.replacePlaceholders(value);
                result.setProperty(newKey, processedValue);
            }
        }
        
        return result;
    }
    
    /**
     * 打印所有配置信息（用于调试）
     */
    public static void printAllProperties() {
        getInstance();
        logger.info("=== Configuration Properties (Profile: {}) ===", activeProfile);
        
        TreeMap<String, String> sortedProps = new TreeMap<>();
        for (String key : mergedProperties.stringPropertyNames()) {
            sortedProps.put(key, mergedProperties.getProperty(key));
        }
        
        for (Map.Entry<String, String> entry : sortedProps.entrySet()) {
            logger.info("{} = {}", entry.getKey(), entry.getValue());
        }
        logger.info("=== End Configuration Properties ===");
    }
}